#include "Acceptor.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "Logger.h"
#include <errno.h>
#include "InetAddress.h"
#include "unistd.h"
namespace mymuduo {

static int createNonblocking() {
    int socketfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
    if(socketfd < 0) {
        LOG_FATAL("%s:%s:%d listen socket create error:%d\n", __FILE__, __FUNCTION__, __LINE__, errno);
    }
    return socketfd;
}

Acceptor::Acceptor(EventLoop *loop, const InetAddress &listenningAddr, bool reuseport) 
    : loop_(loop)
    , acceptSocket_(createNonblocking())
    , acceptChannel_(loop_, acceptSocket_.fd())
    , listenning_(false) {

    acceptSocket_.setReuseAddr(true);
    acceptSocket_.setReusePort(true);
    acceptSocket_.bindAddress(listenningAddr); // 绑定套接字
    // 如果有新用户连接，要执行一个回调（connfd => channel => subloop）
    acceptChannel_.setReadCallback(std::bind(&Acceptor::handleRead, this));
}

Acceptor::~Acceptor() {
    acceptChannel_.disableAll();
    acceptChannel_.remove();
}

void Acceptor::listen() {
    listenning_ = true;
    acceptSocket_.listen();
    acceptChannel_.enableReading(); // channel 注册到 poller
}

// listenfd 有事件发生了，就是有新用户连接了
void Acceptor::handleRead() {
    InetAddress peerAddr;
    int connfd = acceptSocket_.accept(&peerAddr);
    if(connfd >= 0) {
        if(newConnectionCallback_) {
            newConnectionCallback_(connfd, peerAddr); // 轮询找到 subloop 唤醒，分发当前新客户端的 channel
        } else {
            ::close(connfd);
        }
    } else {
        LOG_ERROR("%s:%s:%d accept error:%d\n", __FILE__, __FUNCTION__, __LINE__, errno);
        if(errno == EMFILE) {
            LOG_ERROR("%s:%s:%d socketfd reached limit!\n", __FILE__, __FUNCTION__, __LINE__);
        }
    }
}

}